package com.ophiux.common.log.aspect;

import cn.hutool.core.util.StrUtil;
import com.ophiux.common.core.utils.KeyStrResolver;
import com.ophiux.common.core.utils.SpringContextHolder;
import com.ophiux.common.log.annotation.ExtSysLog;
import com.ophiux.common.log.enums.LogTypeEnum;
import com.ophiux.common.log.event.SysLogEvent;
import com.ophiux.common.log.event.SysLogEventDTO;
import com.ophiux.common.log.util.SysLogUtils;
import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;

import java.lang.reflect.Method;

/**
 * @desc: 操作日志记录处理
 * @author: hhl
 * @date：2022/7/18 16:37
 */
@Slf4j
@Aspect
public class SysLogAspect {
    @Autowired
    private  KeyStrResolver tenantKeyStrResolver;

    public SysLogAspect(KeyStrResolver tenantKeyStrResolver) {
        this.tenantKeyStrResolver = tenantKeyStrResolver;
    }


    @SneakyThrows
    @Around("@annotation(sysLog)")
    public Object around(ProceedingJoinPoint point, ExtSysLog sysLog) {
        String strClassName = point.getTarget().getClass().getName();
        String strMethodName = point.getSignature().getName();
        log.info("[类名]:{},[方法]:{}", strClassName, strMethodName);

        SysLogEventDTO logDTO = SysLogUtils.getSysLog();
        if (!ObjectUtils.isEmpty(sysLog.value())) {
            logDTO.setTitle(sysLog.value());
        } else {  //取接口文档注释
            //获取执行方法
            Method method = ((MethodSignature) point.getSignature()).getMethod();
            //获取防重复提交注解
            ApiOperation annotation = method.getAnnotation(ApiOperation.class);
            logDTO.setTitle(annotation.value());
        }

        logDTO.setMethod(strMethodName);

        // 获取请求body参数
        if (StrUtil.isBlank(logDTO.getParams())) {
            logDTO.setBody(point.getArgs());
        }

        // 发送异步日志事件
        Long startTime = System.currentTimeMillis();
        Object obj;
        try {
            obj = point.proceed();
        } catch (Exception e) {
            logDTO.setLogType(LogTypeEnum.ERROR.getType());
            logDTO.setErrorMsg(e.getMessage());
            throw e;
        } finally {
            Long endTime = System.currentTimeMillis();
            logDTO.setExecuteTime(endTime - startTime);
            logDTO.setTenantId(Long.parseLong(tenantKeyStrResolver.key()));
            SpringContextHolder.publishEvent(new SysLogEvent(logDTO));
        }
        return obj;
    }

}
